package com.google.code.jholidays.events;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;

import org.junit.Test;

import com.google.code.jholidays.core.EventDescriptor;
import com.google.code.jholidays.moc.FixedEventMoc;

public class DependentEventFactoryTest extends DependentEventFactory {
    @Test
    public void testCreate() {
	DependentEventFactory factory = new DependentEventFactory();
	assertNotNull(factory);
    }

    @Test
    public void testDoesntMatchNullDescriptor() {
	DependentEventFactory factory = new DependentEventFactory();
	assertFalse(factory.matches(null));
    }

    @Test
    public void testDoesntMatchInvalidDescriptor() {
	EventDescriptor descriptor = new EventDescriptor(1);
	DependentEventFactory factory = new DependentEventFactory();

	descriptor.setExpression("aabbcc");
	assertFalse(factory.matches(descriptor));

	descriptor.setExpression("123a");
	assertFalse(factory.matches(descriptor));

	descriptor.setExpression("ab123");
	assertFalse(factory.matches(descriptor));

	descriptor.setExpression("44f");
	assertFalse(factory.matches(descriptor));

	descriptor.setExpression("44l");
	assertFalse(factory.matches(descriptor));

	descriptor.setExpression("44h");
	assertFalse(factory.matches(descriptor));

	descriptor.setExpression("0.33");
	assertFalse(factory.matches(descriptor));

	descriptor.setExpression("33.33");
	assertFalse(factory.matches(descriptor));

	descriptor.setExpression("-33.33");
	assertFalse(factory.matches(descriptor));

	descriptor.setExpression("--4");
	assertFalse(factory.matches(descriptor));

	descriptor.setExpression("++4");
	assertFalse(factory.matches(descriptor));

	descriptor.setExpression("+-33.33");
	assertFalse(factory.matches(descriptor));
    }

    @Test
    public void testMatches() {
	EventDescriptor descriptor = new EventDescriptor(1);
	DependentEventFactory factory = new DependentEventFactory();

	descriptor.setExpression("5");
	assertTrue(factory.matches(descriptor));

	descriptor.setExpression("+5");
	assertTrue(factory.matches(descriptor));

	descriptor.setExpression("-5");
	assertTrue(factory.matches(descriptor));

	descriptor.setExpression("0");
	assertTrue(factory.matches(descriptor));
    }

    @Test
    public void testAnalizeInvalidExpression() {
	EventDescriptor descriptor = new EventDescriptor(1);
	DependentEventFactory factory = new DependentEventFactory();

	assertNull(factory.analizeExpression(descriptor, new FixedEventMoc(2)));
    }

    @Test
    public void testAnalizeMissingParent() {
	EventDescriptor descriptor = new EventDescriptor(1);
	DependentEventFactory factory = new DependentEventFactory();

	assertNull(factory.analizeExpression(descriptor, null));
    }

    @Test
    public void testAnalizeInvalidParentID() {
	final int eventID = 1;
	final int parentID = 2;
	final int illegalParentID = 3;

	FixedEventMoc parentEvent = new FixedEventMoc(illegalParentID);

	EventDescriptor descriptor = new EventDescriptor(eventID, parentID);

	assertFalse(parentEvent.getID() == descriptor.getParentID());

	descriptor.setExpression("+5");

	DependentEventFactory factory = new DependentEventFactory();
	assertNull(factory.analizeExpression(descriptor, parentEvent));
    }

    @Test
    public void testAnalizeInvalidExpression2() {
	final int eventID = 1;
	final int parentID = 2;

	FixedEventMoc parentEvent = new FixedEventMoc(parentID);

	EventDescriptor descriptor = new EventDescriptor(eventID, parentID);

	assertEquals(parentEvent.getID(), descriptor.getParentID());

	descriptor.setExpression("abcd");

	DependentEventFactory factory = new DependentEventFactory();
	assertNull(factory.analizeExpression(descriptor, parentEvent));
    }

    @Test
    public void testAnalizeValid() {
	final int eventID = 1;
	final int parentID = 2;
	final int daysCount = 5;

	FixedEventMoc parentEvent = new FixedEventMoc(parentID);

	EventDescriptor descriptor = new EventDescriptor(eventID, parentID);

	assertEquals(parentEvent.getID(), descriptor.getParentID());

	descriptor.setExpression(String.valueOf(daysCount));

	DependentEventFactory factory = new DependentEventFactory();
	IEvent event = factory.analizeExpression(descriptor, parentEvent);
	assertNotNull(event);

	// validate fields
	assertTrue(event instanceof DependentEvent);
	assertEquals(event.getID(), eventID);
	assertSame(event.getDescriptor(), descriptor);

	DependentEvent evt = (DependentEvent) event;
	assertNotNull(evt.getParent());
	assertSame(evt.getParent(), parentEvent);
    }
}
